<?php

namespace App\Supports\BatchChunk;

use Closure;
use RuntimeException;

class BatchChunk
{
	protected $builder = null;
	
	public function setBuilder($builder)
	{
		$this->builder = $builder;
		return $this;
	}
	
	public function forBatchAfterId($perPage = 15, $lastId = 0, $orderDirection = 'asc', $orderColumn = 'id')
	{
		$clone = clone $this->builder;
		if (! is_null($lastId) and $orderDirection === 'asc') {
			$clone->where($orderColumn, '>', $lastId);
		}
		if (! is_null($lastId) and $orderDirection === 'desc') {
			$clone->where($orderColumn, '<', $lastId);
		}
		return $clone->orderBy($orderColumn, $orderDirection)->limit($perPage);
	}
	
	public function chunks($count, Closure $closure, $orderDirection = null, $orderColumn = null)
	{
		$orderDirection = $orderDirection ?? 'asc';
		
		$orderColumn = $orderColumn ?? 'id';
		
		$lastId = null;
		
		do {
			
			$results = $this->forBatchAfterId($count, $lastId, $orderDirection, $orderColumn)->get();
			
			$resultsCount = $results->count();
			
			if ($resultsCount == 0) break;
			
			if ($closure($results, $lastId) == false) return false;
			
			$lastId = $results->last()->{$orderColumn};
			
			if ($lastId === null) {
				throw new RuntimeException("The chunks operation was aborted because the [{$orderColumn}] column is not present in the query result.");
			}
			
			unset($results);
			
		} while ($resultsCount == $count);
		
		return true;
	}
}
